﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WTwitter.Model.Framework {
	enum EventType {
		/// <summary>
		/// 単純な進捗メッセージ
		/// </summary>
		Progress,
		/// <summary>
		/// エラー
		/// ※ある程度頻繁に起こりえるもの（リクエストのタイムアウトとか）
		/// </summary>
		Error,
		/// <summary>
		/// 致命的なエラー
		/// ※これはずっと残るようにする予定
		/// </summary>
		CriticalError
	}

	sealed class MessageInfo {
		public EventType Type { set; get; }

		/// <summary>
		/// メッセージの要約（１行に収まる程度）
		/// </summary>
		public string Message { set; get; }

		/// <summary>
		/// メッセージの詳細
		/// （必要に応じて）
		/// </summary>
		public string Detail { set; get; }

		/// <summary>
		/// メッセージが発行された時間
		/// </summary>
		public DateTime Time { set; get; }
	}

	sealed class MessageAddedEventArgs : EventArgs {
		public MessageAddedEventArgs(MessageInfo newItem) {
			Item = newItem;
		}

		/// <summary>
		/// 新しく追加されたメッセージ
		/// </summary>
		public MessageInfo Item { private set; get; }
	}

	/// <summary>
	/// イベントやエラーなどの情報を登録する
	/// 登録された情報はViewModelで拾ってWindowに表示されたり、ログに出力されたりする（予定）
	/// </summary>
	static class Message {
		#region private member
		private static object lockObj = new object();
		private static List<MessageInfo> _messageLog = new List<MessageInfo>();
		private const int _logNum = 200;
		private static List<MessageInfo> _criticalErrorLog = new List<MessageInfo>();
		#endregion

		/// <summary>
		/// メッセージが追加された通知イベント
		/// </summary>
		static public event EventHandler<MessageAddedEventArgs> MessageAdded;

		static Message() {
			MessageAdded += (sender, e) => {};
		}

		/// <summary>
		/// メッセージを追加する
		/// </summary>
		/// <param name="type"></param>
		/// <param name="message">メッセージの簡略表示（１行で収まる程度）</param>
		/// <param name="detail">詳細</param>
		static public void Add(EventType type, string message, string detail) {

			var item = new MessageInfo() {
				Type = type,
				Message = message,
				Detail = detail,
				Time = DateTime.Now
			};

			//複数のスレッドから同時にメッセージが飛んでくるかもしれないのでlockする
			lock (lockObj) {
				_messageLog.Add(item);
				if (_messageLog.Count > _logNum) {
					_messageLog.RemoveAt(0);
				}

				if (type == EventType.CriticalError) {
					_criticalErrorLog.Add(item);
				}
			}

			var handler = MessageAdded;
			handler(null, new MessageAddedEventArgs(item));
		}

		/// <summary>
		/// メッセージを追加する
		/// </summary>
		/// <param name="type"></param>
		/// <param name="message">メッセージの簡略表示（１行で収まる程度）</param>
		static public void Add(EventType type, string message) {
			Add(type, message, "");
		}
	}
}
